﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;

namespace BJoin.Algo
{
    public static class ShuffleHelper
    {
        /// <summary>
        /// 洗牌算法
        /// </summary>
        /// <typeparam name="T">TType</typeparam>
        /// <param name="source">源集合</param>
        /// <returns>目标集合</returns>
        public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
        {
            return Shuffle<T>(source,source.Count());
        }
        /// <summary>
        /// 抽奖算法
        /// </summary>
        /// <typeparam name="T">TType</typeparam>
        /// <param name="source">源集合</param>
        /// <param name="takeNum">数目</param>
        /// <returns>目标集合</returns>
        public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, int takeNum)
        {
            Validation(source.Count(), takeNum);
            T[] elements = source.ToArray();
            int y = elements.Length - 1;
            for (int i = takeNum - 1; i >= 0; i--)
            {
                int swapIndex = RandomNumberGenerator.GetInt32(y);
                yield return elements[swapIndex];
                elements[swapIndex] = elements[y];
                y -= 1;
            }
        }
        private static void Validation(int total, int take)
        {
            if (take > total) throw new ArgumentException("take's num cannot great than source's num");
        }
    }
}
